package com.dailyblue.example.spring.boot.seckill.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.dailyblue.example.spring.boot.commons.bean.Goods;
import com.dailyblue.example.spring.boot.commons.util.JsonResult;
import com.dailyblue.example.spring.boot.commons.util.ResultTool;
import com.dailyblue.example.spring.boot.seckill.service.SeckillService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

@Service
@Slf4j
public class SeckillServiceImpl implements SeckillService {
    @Resource
    private StringRedisTemplate stringRedisTemplate;

    private static final String PROXY = "GOODS_SECKILL_";

    private boolean flag = true;

    // 初始化操作
    public void init() {
        // 向redis中存放10件商品
        Goods goods = new Goods(1, "可口可乐", 1.9);
        ValueOperations<String, String> values = stringRedisTemplate.opsForValue();
        ListOperations<String, String> lists = stringRedisTemplate.opsForList();
        for (int i = 0; i < 10; i++) {
            lists.leftPush(PROXY + "LIST", JSONArray.toJSONString(goods));
        }
        // 库存量
        values.set(PROXY + "STOCK_NUMBER", "10");
    }

    @Override
    public JsonResult seckill(String user) {
        if (flag) {
            init();
            this.flag = false;
        }
        ValueOperations<String, String> values = stringRedisTemplate.opsForValue();
        ListOperations<String, String> lists = stringRedisTemplate.opsForList();
        // 你开始秒杀的时间是否在规定时间里 假设10：45
        Date seckill_date = new Date(124, 0, 15, 10, 45, 0);
        Date now_date = new Date();
        if (now_date.before(seckill_date)) {
            return ResultTool.fail(501, "秒杀还没有开始");
        }
        // 一个用户不能重复购买
        Boolean hasKey = stringRedisTemplate.hasKey(PROXY + user);
        if (hasKey) {
            return ResultTool.fail(502, "单个用户不能重复购买");
        }
        // 是否已卖完
        String stock_number = values.get(PROXY + "STOCK_NUMBER");
        if (stock_number.equals("0")) {
            return ResultTool.fail(503, "秒杀活动已结束");
        }
        stringRedisTemplate.watch(PROXY + "STOCK_NUMBER");
        SessionCallback<List<Object>> sessionCallback = new SessionCallback<>() {
            @Override
            public <K, V> List<Object> execute(RedisOperations<K, V> operations) throws DataAccessException {
                // 开启事务
                stringRedisTemplate.multi();
                // 减库存
                values.decrement(PROXY + "STOCK_NUMBER");
                // 出货
                String goods = lists.rightPop(PROXY + "LIST");
                // 添加购买记录
                values.set(PROXY + user, JSONArray.toJSONString(goods));
                // 执行事务
                return stringRedisTemplate.exec();
            }
        };
        List<Object> execute = stringRedisTemplate.execute(sessionCallback);
        log.info("execute:{}", execute);
        if (execute.get(1) == null || execute.get(1).toString().equals("")) {
            return ResultTool.fail(501, "抢购失败！");
        }
        return ResultTool.success("success");
    }
}
